﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Workflows.Components.TextMining.Clustering
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="clusterCount"></param>
    /// <param name="remainingDocCount"></param>
    /// <param name="message"></param>
    /// <param name="percent"></param>
    public delegate void ClusterStatusChanged(int clusterCount, int remainingDocCount, string message, int percent);

    /// <summary>
    /// 
    /// </summary>
    public interface IDocumentCluster
    {
        event ClusterStatusChanged OnClusterStatusChanged;

        /// <summary>
        /// determine distance between nodes
        /// </summary>
        IDistanceCalculator DistanceCalculator { get; set; }

        /// <summary>
        /// evaluate results
        /// </summary>
        IPurityCalculator PurityCalculator { get; set; }

        /// <summary>
        /// term id -> non-zero term weight (default to 0 and when calc scaling, it's 1+weight)
        /// </summary>
        Dictionary<int, double> TermWeights { get; set; }

        /// <summary>
        /// flag indicating if a doc can belong to more than one categories
        /// </summary>
        bool CanOverlap { get; set; }

        /// <summary>
        /// reassociation lookup distance over current cluster distance ratio
        /// </summary>
        double ReassociationRange { get; set; }

        /// <summary>
        /// optional settings
        /// </summary>
        /// <param name="termCoverageThreshold"></param>
        /// <param name="termFreqThreshold"></param>
        /// <param name="clusterDistanceThreshold"></param>
        void SetThreshold(double termCoverageThreshold, double termFreqThreshold, double clusterDistanceThreshold);

        /// <summary>
        /// given doc term list, return clustered documents
        /// </summary>
        /// <param name="docTerms">doc id -> list of terms</param>
        /// <param name="nGramLength"></param>
        /// <param name="useNGram"></param>
        /// <returns>cluster id -> ClusterNode</returns>
        Dictionary<int, ClusterNode> ClusterDocuments(
            Dictionary<int, Dictionary<int, DocTermFreq>> docTerms,
            bool useNGram, int nGramLength);

        /// <summary>
        /// in addition to exact term match, it also try to match 
        /// root of terms
        /// </summary>
        /// <param name="docTerms"></param>
        /// <param name="termStemmings1"></param>
        /// <param name="termStemmings2"></param>
        /// <returns></returns>
        Dictionary<int, ClusterNode> ClusterDocuments(
            Dictionary<int, Dictionary<int, DocTermFreq>> docTerms,
            Dictionary<int, string> termStemmings1,
            Dictionary<string, List<int>> termStemmings2);
    }
}
